package com.tudouji.framework.task;


import com.sun.org.apache.xpath.internal.operations.String;
import com.tudouji.common.enums.CopyTypeEnums;
import com.tudouji.common.enums.IsCopyEnums;
import com.tudouji.common.utils.DateUtils;
import com.tudouji.common.utils.StringUtils;
import com.tudouji.project.bill.domain.Producereport;
import com.tudouji.project.bill.domain.Producereportitem;
import com.tudouji.project.bill.service.IProducereportService;
import com.tudouji.project.bill.service.IProducereportitemService;
import com.tudouji.project.copy.domain.Copyparam;
import com.tudouji.project.copy.service.ICopyparamService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 每日定时任务，针对已完成的生产计划生成生产报表、明细
 */
@Slf4j
@Component("ProduceDataTask")
public class ProduceDataTask {

    @Autowired
    private ICopyparamService copyparamService;

    @Autowired
    private IProducereportService producereportService;

    @Autowired
    private IProducereportitemService producereportitemService;

    //同步参数 startdate,时间更新处理，原因是时间间隔过大，会导致内存溢出，或者任务时间太长等问题
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public void produceDataTask() {
        //1.查询同步参数
        Copyparam copyparam = new Copyparam();
        copyparam.setType(CopyTypeEnums.PRODUCTION_OUT.getCode());
        copyparam.setIscopy(IsCopyEnums.YES.getCode());
        List<Copyparam> copyparams = this.copyparamService.selectCopyparamList(copyparam);
        //2.针对每一个生产计划，写入几条对应的领料单主表------主表数据缺：总入库重量，总出库重量，总退料重量
        List<Producereport> prs = producereportService.selectPRData(copyparams.get(0).getStartdate());

//        java.lang.String nowStr = DateFormatUtils.format(copyparams.get(0).getStartdate(), "yyyy-MM-dd");
        //写入历史数据
//        producereportService.insertReportHistory(nowStr);
//        producereportService.insertReportItemHistory(nowStr);
        //删除历史数据
//        producereportService.deleteAllItem(nowStr);
//        producereportService.deleteAll(nowStr);
        if (prs.size() > 0){
            for (int i = 0; i < prs.size(); i++) {
                Producereport rep = prs.get(i);
                insertPort(rep);
                //领料出库单
                List<Producereportitem> itemsOut = selectOutItem(rep.getPlcode());
                //领料出库单对应的产成品入库单
                List<Producereportitem> itemsIn = selectinItem(rep.getPlcode());
                insertItem(rep, itemsOut, itemsIn);
                updatePort(rep);

                //生产计划的状态为5
                producereportService.updateProducePlan(rep.getPlanguid());
            }
        }else{
            log.info("生产报表查询结果为空！");
        }
    }

    /**
     * @Author shaodong
     * @Description 查询对应领料单的入库申请单所关联的入库明细，按照库房，库间，规格，单位id汇总 -->n条
     * @Date 14:04 2021/7/3
     * @Param
     * @return
     **/
    private List<Producereportitem> selectinItem(java.lang.String plcode) {
        return producereportitemService.selectProducereportitemByPlcodeIn(plcode);
    }

    /**
     * @Author shaodong
     * @Description 查询对应领料单的重量，按照部门，库房，库间，规格，单位id汇总 --->m条
     * -- 缺: 主表id、部门名称、部门id、
     * @Date 13:56 2021/7/3
     * @param plcode 领料单code
     * @return
     **/
    private List<Producereportitem> selectOutItem(java.lang.String plcode) {
        return producereportitemService.selectProducereportitemByPlcode(plcode);
    }

    private void updatePort(Producereport report) {
        report.setEndtime(new Date());
        producereportService.updateProducereport(report);
    }

    /**
     * @Author shaodong
     * @Description 循环m条出库数据，每次插入n条生产报表明细，插入出库平均明细重量计算公式为【针对m中的每一条规格重量】：出库总重量 * （入库明细重量/入库明细总重量）
     * -- 如果是辅料，按照出库成本对象与入库明细比较，写入对应入库明细即可
     * @Date 14:24 2021/7/3
     * @Param
     * @return
     **/
    private void insertItem(Producereport rep, List<Producereportitem> pickOutitems, List<Producereportitem> pickInitems) {
        BigDecimal allOutWeight = BigDecimal.ZERO;
        BigDecimal allInWeight = BigDecimal.ZERO;
        //首先计算得出所有入库产品的总重量
        for (int i = 0; i < pickInitems.size(); i++) {
            allInWeight = allInWeight.add(pickInitems.get(i).getInweight());
        }
        //循环处理每一个领料出库明细，对每一条出库明细，按照产品入库明细生成金蝶的领料出库分录
        for (int i = 0; i < pickOutitems.size(); i++) {
            Producereportitem pickOutitem = pickOutitems.get(i);
            pickOutitem.setProducereportid(rep.getId());
            pickOutitem.setDepartid(rep.getDepartid());
            pickOutitem.setDepartname(rep.getDepartname());
            if (1 == pickOutitem.getInsptype()){//主料
                setItemInWeight(pickOutitem, pickInitems, allInWeight, false);
            }
            if (2 == pickOutitem.getInsptype()){//辅料
                setItemInWeight(pickOutitem, pickInitems, allInWeight, true);
            }
            allOutWeight = allOutWeight.add(pickOutitem.getOutweight());
        }
        rep.setBackweight(producereportService.selectMaterial(rep.getPlcode()));
        rep.setInweight(allInWeight);
        rep.setOutweight(allOutWeight);
    }

    /**
     * @Author shaodong
     * @Description
     * @Date 15:13 2021/7/3
     * @Param item  出库明细一条
     * @Param itemsIn   入库总明细
     * @Param allInWeight   规格总入库重量
     * @Param isFL 是否是辅料
     * @return
     **/
    private void setItemInWeight(Producereportitem item, List<Producereportitem> itemsIn, BigDecimal allInWeight, Boolean isFL) {
        BigDecimal itemAllOutWeight = BigDecimal.ZERO;
        if (isFL && itemsIn.size() == 0){
            log.info("辅料并且没有入库单的情况下，插入明细"+ item);
            producereportitemService.insertProducereportitem(item);
        }else{

            for (int i = 0; i < itemsIn.size(); i++) {
                Producereportitem itemIN = itemsIn.get(i);

                if (!isFL || (isFL && StringUtils.equalsAny(itemIN.getInspecid(), item.getCospguid()))) {
                    itemIN.setProducereportid(item.getProducereportid());
                    itemIN.setDepartid(item.getDepartid());
                    itemIN.setDepartname(item.getDepartname());
                    itemIN.setSrguid(item.getSrguid());
                    itemIN.setSrname(item.getSrname());
                    itemIN.setShrguid(item.getShrguid());
                    itemIN.setShrname(item.getShrname());
                    itemIN.setOutproductid(item.getOutproductid());
                    itemIN.setOutproduct(item.getOutproduct());
                    itemIN.setOutspecid(item.getOutspecid());
                    itemIN.setOutspecname(item.getOutspecname());
                    itemIN.setInsptype(item.getInsptype());
                    itemIN.setOutstockunit(item.getOutstockunit());
                    itemIN.setOutstockunitid(item.getOutstockunitid());
                    //20220527，区分主料还是辅料
                    if (isFL){
                        itemIN.setCospguid(item.getCospguid());
                    }else{
                        itemIN.setCospguid(itemIN.getInspecid());
                    }

                }

                if (isFL && StringUtils.equalsAny(itemIN.getInspecid(), item.getCospguid())){
                    itemIN.setOutweight(item.getOutweight());
                }

                if (!isFL){
                    if (itemsIn.size()-1 == i){
                        itemIN.setOutweight(item.getOutweight().subtract(itemAllOutWeight));
                        producereportitemService.insertProducereportitem(itemIN);
                        continue;
                    }
                    itemIN.setOutweight(item.getOutweight()
                            .multiply(itemIN.getInweight()
                                    .divide(allInWeight, 4, BigDecimal.ROUND_HALF_UP)));
                    itemAllOutWeight = itemAllOutWeight.add(itemIN.getOutweight());
                }
                producereportitemService.insertProducereportitem(itemIN);
            }
        }
    }

    private Producereport insertPort(Producereport rep) {
        rep.setCreattime(DateUtils.getNowDate());
        rep.setStarttime(DateUtils.getNowDate());
        producereportService.insertProducereport(rep);
        return rep;
    }
}
